テスト Tips
テストケース・テストコード実装 戦術
hr.icon
原則として、テストコードにロジック(条件分岐とか特に)を入れるな
本番コードのテストをするための、テストコードにバグがあると、テストしても意味がない。
本番コードにバグがないことを保証できない。
テストコードの中にロジックが入ってしまうと、テストコードにバグを入れ込む確率が高くなってしまう。
なので、極力ロジックをテストコードに入れるな。
テストコードが肥大化してきて「ああ、ちょっと保守しないとヤバそう」って時に、ようやく検討し始めろ。
ただし、それでも複雑なロジックは入れるなよ。
テストコードのテストをしないといけなくなるぞ...???
テストケース1つ1つがシンプルで読みやすくなるように心がけろ
上の「複雑なロジックを入れない」と同じようなことだが、これも大事。
プログラミング初心者が使うような文法、内容で、めっちゃわかりやすくかけ。
カッコつけたコードを書くな。
テストケースでどういうことをしてるのか、パッとわかる状態にしてほしい。
共通関数とかを最初から使おうとするな、テストコードをDRYにしようとするな
無理にDRYとかし始めると、テストコードにバグが含まれる可能性が高くなる。
何度も言うが、テストコードにバグが入る余地を許してはいけない。
最初からDRYにする意味とかあんまない。
テストコードが肥大化してきて「あかん、もう無理、、、、」てなった時に初めて検討しろ。
テスト対象の優先順位を意識してみては?
全ての本番コードに対して、全パターンのテストケースを書く必要はない。そんなことしたら大変やろうが。
Googleでもカバレッジは75%くらいでいい的な話もあるくらいだ。
以下の判断基準を参考に、優先度高い対象からテストしていけ。
「セキュリティに関わるとこ」「システムの核となる機能」「お金が関わるとこ」などなどは、マジでちゃんとテストを書くようにしろ。もう、一瞬のミスも許されないくらいテストしろ。
逆に簡単に結果がわかるような対象のテストはしなくていい。してもあんま意味ない。
フレームワークやライブラリの機能も、基本はテストしなくていい。作った奴らが勝手にやってくれてるはず。
ただ、利用者が少ないライブラリや、バグが入ってると困る箇所などは、安全のためテストしとくのもあり。
テストケースに抜け漏れが無いようにしよう
抜け漏れが入らないようにするためのテスト技法があるから、それを学んでいこうぜ。
参考:「はじめて学ぶソフトウェアのテスト技法」
データの更新や削除を伴うテストを書く場合は、before/afterの両方を検証する。(afterだけ検証して満足しない)
何か更新系処理を実行し、その後の値を検証する場合は、更新前の値も検証しておく。
もし、更新前の値が期待通りじゃなかったのに、更新後の値が期待通りになった場合は、テスト対象の処理にバグがあることを意味する。
なので、beforeが期待通りであることもちゃんとテストする。
テストコード全体がなるべく1画面に収まるようにする
便利関数や準備が重すぎて、1つのテストケースの内容を簡単に理解できないのはだるい。
この状態は、たぶんテストが複雑化してることを意味してそうではある。
例えば、多段のbefore条件があって、その前提からテストしてるケースなど。
これやると、マジでテストコードにバグが入り込みやすくなって、テストの保守がクソだるくなりうるので、マジで注意。
安易にテストをDRYにするな。テスト前Setupとかも、そのテストケースに近いところでやれ。
DRYを捨てた結果、仕様変更が発生したときに大量のテストが壊れて修正が必要になる問題はある程度許容する
テストていうのは、本番コードの仕様に対して必要十分な量で作るもんだ。
本番コードの仕様が変わったら、テストの内容も変える必要が出てくるのは自然の摂理。
なので「仕様変更に対してテスト壊れるのだりぃ」とか言わず、仕様変更があったら一緒にテストも変更するのがセットだと思って挑め。
いつでも、どこでも、誰がどんな順番で何度実行しても、パスするテストを書く
開発PCに依存するようなテストとか書くなってこと。
こんなことしたら正しいテストにはならんでしょうが。
個別の前提条件に依存するようなテスト書くんじゃねぇよ、使い物にならねえよそんなもん。
privateメソッドは直接テストしない
内部実装に対してテストは書くな。
内部実装なので変更されやすいということを理解しておけ。
もしテスト書いてたら、内部実装を変更する、リファクタリングするのが億劫になってしまう。
AAA(Arrange、Act、Assert)を意識したテストコードを書く
Arrange(準備)、Act(実行)、Assert(検証)。
どのテストケースでもこの順番を意識して書くと、テストコード全体が読みやすくなるだろう。
一貫性が大事なのさ何事も。
とにかくテストコードは、非エンジニアすらも仕様として読める状態にしておけ
どんなテストケースをどういう意図でテストしてるのか、これがぱっと見でわかるようでなければクソだ。
テストケース、テストコードの内容を把握するために、メモリを消費させるんじゃねえよ。
メモリを消費させるような、テストケース、テストコードは、ケースに漏れがあったり、テストコード自体にバグがあったりする可能性が高え。
テストケース同士の「独立性」を保つように意識しろ
例えば、複数のテストケースが同じ前提条件(ex: fixture)を元にテスト実行してる場合は、独立性がないという。
こういう状態は、少し危険。あるテストケースのために前提条件変更した際、別のテストケースに影響してテストコードがバグったりする。
あと、テストケースAが終わらないとテストケースBがうまくいかないみたいな「順序性」も入れてはいけない。
そういうのもテストコードが不安定になる要因。
とにかく、原則として、テストケースごとの「独立性」を保つようにしよう。
ただし、明らかに前提条件が一緒などの場合は、一緒にしちゃってもいい。
ただ、バランス考えようねって話。
重複が問題になるまでは、別々に前提条件をコードとして準備してた方が安全そうではある。
テストケースを見ただけで、本番コードの仕様が把握できるようにしておけ
テストコードを読んだときに、パッと見て本番コードはこういう仕様なんだなと分かるようにしよう。
そうすると、漏れてるテストケースとかも見つけやすくなるし。
本番コード変更の際もテストコードを修正しやすくなる。
明らかに明白な動作はテストケースを作る意味があまりない
onigiri.w2.iconの性格的に、これやると、本当にテストすべきコードとかも無視してしまう可能性がある...。
けどまあ、理論的にはそうだろうなと理解してる。
テストコード実践 戦術(番外:モック編)
hr.icon
単体テスト・結合テスト・システムテストの使い分け 戦略
hr.icon
注意.icon 結合テストに関しては、まだよくわからん...ので一旦放置。実戦で回しながらTips拾っていく...onigiri.w2.icon
「システムテスト」「統合テスト」「ユニットテスト」の違いざっくりイメージ
システムテスト:システム全体の動作確認的なイメージ
統合テスト:部品同士を組み合わせてテストしたり、外部システムと連携してテストしたり、ユニットテストで庇い切れなかった箇所(モック or 実体を利用してテストするのにコストかかる)をテストしたり。
ユニットテスト:コードだけで確認できる部品単体レベルの動作チェック
単体テスト対象の話
・依存関係がほとんどなくて明白でない動作を持つコードは単体テストしろ
・依存関係が多くて明白な動作を持つコードは無視しろ。わんちゃん結合テスト行き
・依存関係が多くて複雑な動作を持つコードは本番側を分解して改善しろ
・依存関係がほとんどなくて明白な動作を持つコードは無視しろ
そもそも単体テスト・結合テストという分け方自体がナンセンスらしい。両者は分けづらいとのこと
テストピラミッドを意識して、単体テストの量を増やすといい
https://scrapbox.io/files/63faf59c5959a4001bbc235b.png
下段に行くほど、テストコストが低く、安定することになる。
なので、UTの量を増やし、逆にシステムテストの量を減らせるように持っていくことが大事。
そうはいっても、無理にUTに寄せようとしなくても良いと思うonigiri.w2.icon
UTできないものに関しては、ITやSTに回す感じで。
ただ、UTできない本番コードは設計を見直した方がいい可能性もあることを認識しておくこと。
テストケース選定手法
hr.icon
「はじめて学ぶ ソフトウェアのテスト技法」より...
ブラックボックステスト
同値クラス
同じ種類の結果が出るデータの集合を同値クラスという。
例えば、引数aがあったとして、a=1の場合結果がtrue、a=2の場合結果がtrueなら、2つのデータ(1, 2)は同値クラスと呼ぶ。
この同値クラスに関しては、1つの値を代表値として選んでテストケースを作るといい。
境界値
同値クラスの中でも、境界値の部分は確実にテストしておくべき。
例えば、1~10の場合はtrue, 11~20の場合はfalse的なパターンがあったとしたら、、、
1, 10, 11, 20ていう値はテストしておく。
あと、0, 21っていう同値クラス外の境界値もテストしておくと良い。
デシジョンテーブル
以下参考画像
https://scrapbox.io/files/63fadda82be26f001b552a7f.png
複数条件があった場合、その組み合わせに対して起きてほしい結果を表にする方法。
上段:条件一覧
下段:その条件の組み合わせで起きることが期待される結果(アクション)
Y, Nの条件以外の範囲系の条件でも上手いことやればいいよ
table: 例
1 2 3 4 5 6
平日 Y Y Y N N N
年齢 0~18 19 ~29 30 ~ 0 ~ 18 19 ~ 29 30 ~
構成ペア
これは上記のような条件の組み合わせが多すぎた際に、テストケースを減らすための手法。
todo.icon(現状、いまいち理解はできてない...)onigiri.w2.icon
ドメイン分析
あるクラスの変数単体で見たら有効な場合でも、複数の変数を組み合わせた条件の場合は無効ってこともある。
そういう条件をちゃんと見つけて、テストケースに落とす。
状態遷移
状態遷移する系のクラス、モデルなどに対して、テストケースを作る際の手法。
状態遷移図をちゃんと書いて、その状態遷移の全パスを少なくとも1回は網羅するようにテストケースを作成する。
ユースケース
システム設計で最後にやるようなテスト。
システムに対して決められたユースケースがあるので、そのユースケース詳細通りに動くかをテストする。
Q&A
q.icon 結合テストを使うタイミングがいまいちわからんな。単体テストやと対象がわかりやすいやん。結合テストってどういう風にテスト対象を決めていくわけ?そもそも目的があまりわからん。
a.icon
hr.icon
hr.icon
期待値は変に計算したり変数使ったりするよりも、可能ならベタ書きにしよう
そっちの方が、どういう結果になって欲しいのかが一目瞭然になる。
まあ、pytest.mark.parametrizeとか使ったテストだと無理そうだがonigiri.w2.icon
ストコードにロジックを持ち込むな。常にベタ書きを意識しろ
テストコードは常に正常に動く状態にしておきたい。
テストコードにロジックを入れてしまうと、そのロジックのテストをしないといけなくなる...
こんなことやってられないので、テストコードにロジックを入れたり、複雑にしたりするなよ。
とにかく、シンプルで簡単なコード。重複しててもいいから、ミスが入り込まないコードを意識しろ。
ロジックを入れたとしても、めっちゃ簡単なロジック。結果が見えるような簡単なロジックならOK。
ただ、それでも危険だがな。
ベタ書きにすると、仕様変更に対してテストコードが壊れやすくなる
実装側の仕様変更した際、テストコードも一緒に変更しないといけない状況が生まれやすくなる。
むしろ、そうなるのが自然だと私は思うがonigiri.w2.icon
実装コードの仕様が変わったのなら、テストコードも変えるべき。
逆に、実装コードの仕様が変わらず、具体だけが変わっただけなのに、テストコードを変えないといけない状況は、むしろ欠陥だと思う。
その仕様に合わせて必要十分なテストコードを書くべきonigiri.w2.icon
変に将来を予想してテストコードを書くのは、言語化できないが無駄な気がする。
だから、常に仕様に対して必要十分なテストコードを書く。
この前提からすると、実装側の仕様が変わるなら、そりゃテストコードも壊れる可能性は高いだろうと。
仕様が変わったなら、テストコードも変えるのは当たり前。
テストコードに条件分岐とか入れるなよ?w
これは入れてはいけない。危なすぎるonigiri.w2.icon
普通にテストケースを分けろ。
その他感想
DRYって、コードの重複を無くすって意味では無かった気がするonigiri.w2.icon
なんやったかな。概念の重複を無くす的な意味だった気がするonigiri.w2.icon
概念が別なら、例え同じコードであっても一緒にするなと。
将来、片方の概念に対しての変更があった際に、もう片方にも変更が影響してしまうよ?と。
テストコードはアプリケーションの命綱、安全ネット、防弾チョッキ
「このコード、テストなしでリリースするのはちょっと不安だな」と思ったら、それがテストを書くトリガー
リリースするときに「ちゃんとうまく動きますように」と祈ってる自分がいたら、テストが不足している証拠
うん、そうだなonigiri.w2.icon
システムを作る部品がそいつが持つ責務どおりの動作が保証されてないと、システムがちゃんと動くわけがない。
だから、少なくとも単体テストは絶対に必要だと思ってる。
単体テストなしで、統合テストだけしとけって話もあるが、、、
ん〜〜、ここら辺の話はまだ自分にはよくわからん
単体テストの方が効率良くね?とは思う。
統合テストでバグ見つかった際、どの部品が悪さしてるのか見つけにくくね?とか思ったりする。
将来の自分が楽をするために書く
コマンド一発でこれまで書いてきたコードの動作確認ができる! 速いし、楽ちん!!
毎回リリース前に全部手作業と目視でテストするつもり?無理だよね!
再帰テストの話かなonigiri.w2.icon
例えば、将来コードを変更した際に、部品にバグがあったらリリース前に発見できるようにしたい。
そのためにテスト書いて、自動で変更に対するバグチェックができる状態にしておこうと。
将来、自分のコードをメンテするかもしれない他のメンバーのために書く
ドキュメントを書く代わりに、コードを書いた人の意図や頭の中にある仕様を明示的なテストコードとして残しておく
テストコードで、どういう動きをテストしてるのか確認することで、その実装コードが満たすべき仕様を把握できるonigiri.w2.icon
ドキュメントはいらない。
これはあれだな、単体テストの話が特に顕著かもな。
テスト対象になるところの例:「複雑なロジック」「お金周りのロジック」などなど
「バグ入り込みやすそう」「ここだけは絶対に失敗させてはいけない」みたいな箇所を重点的にテストするって感じかなonigiri.w2.icon
極端な話、「プロパティが正しく表示されるか」とかテストなんてせんでいい。
普通に表示されるやろ。っていう。
例外処理の機構、仕組みは確かにしっかりテストしてた方がいい気がしたonigiri.w2.icon
例外処理バグって、エラー内容がロギングされたないとか最悪。
基本的にフレームワークやライブラリのテストはしなくていい、が、、、心配な動作があるならテストしておくに越したこともない
基本的にはフレームワーク、ライブラリなんてのはテストされてるから、その機能をテストするのは意味ないonigiri.w2.icon
ただし、そいつらも完璧ではないから、ミスってることもあると思う。
慎重になりたい機能に関わってるところなどは、念の為テストはしてた方がいいかも。
あと、使ってる人が少ないフレームワーク・ライブラリとかは、バグ発生率が高くなりそうではある。
テストの技法を学びたいなら「はじめて学ぶソフトウェアのテスト技法」を読んでみるといいよ
読んでみます!!!時間があれば。いやでも一冊は持っておきたいか...onigiri.w2.icon
テストコードを書く際の注意点
1. ヌケ・モレのない、必要最小限のテスト項目を抽出する
このMECEにテスト項目を抽出する技法を知らんくて、結構独自に雑にケース出してる...
一回学んでおくべきかもな..
2. データの更新や削除を伴うテストを書く場合は、before/afterの両方を検証する。(afterだけ検証して満足しない)
なるほどなるほどonigiri.w2.icon
確かにそうやな。いつもafterだけ意識してた気がするわ。beforeも大切な気はする。
ロジックはbeforeが正しい前提で動いてるはず、beforeが間違った上でのafter結果検証では、ロジックが間違ってる可能性もある...
3. 上から下へ、素直に読み下せるテストコードを書く(過度なDRYを目指すのはNG、便利関数の使いすぎも危ない)
とにかくシンプルにしようね。
なんか便利関数とか入り込みまくると、テストコード読む気失せるでマジで。
プログラミング初心者が使うようなコード書いていこう。それが一番読みやすい。
4. テストコード全体がなるべく1画面に収まるようにする
これよくわからん。まだ理解できないonigiri.w2.icon
beforeとかテストコード前の前提条件を別のところで書いたりするな、的なこと言ってるのかな。
1画面でテスト内容を理解できるようにしろ的な?
まあ、でも言いたいことはわかる。
画面を行ったり来たりしてコードを読むのはしんどいかも、うん。なんとなく言いたいことはわかる。
1つのテストケースの内容を一瞥で理解できるようにしようって話やな。
そうしないと、テストコードの保守とかに対しての気持ちが失せるわ。
5. 複雑なテストコードのデメリットを理解する
まあ、これやると、テストコードにバグが発生するとか起きうるし。
テストコードの保守がだるいとか、何が起きてるのかよくわからん...みたいなことが起きうる。危ない。
基本、準備が大量に必要なテストは、こうなりがちな気がするなonigiri.w2.icon
データベースに接続する必要あるとか。
データベースを準備して、なんか開いて、みたいなややこしいことをテスト前にすることになり、コードが汚くなるだろう。
ここらへんは、技術でどうにか埋めていくしかない。
あとは設計がややこしすぎて、1つの部品に対するテストがややこしくなってしまう的なのもありそう。
これは設計の見直しが必要ってやつになるのかもしれない。
それができないなら、テストコードをできる限りきれいにするよう頑張ろう。
6. DRYを捨てた結果、仕様変更が発生したときに大量のテストが壊れて修正が必要になる問題はある程度許容する
そうね、基本的には複雑にならないよう、ガンガンDRYを許容していこうonigiri.w2.icon
7. 実際のユースケースが想像できるテストデータを用意する
なんで??onigiri.w2.icon
なんかわからんけど、まあユースケースを想像しやすいから、テスト内容も把握しやすい的な?
8. いつでも、どこでも、誰がどんな順番で何度実行しても、パスするテストを書く
これはマジでそうだと思うonigiri.w2.icon
環境変数とか関わり始めたら、そのPCに依存したテストコードとかになるだろう。うん。
9. privateメソッドは直接テストしない
うん、そうね。privateはあくまで内部実装。
内部実装やから、変更されやすい。そこに対してテストしちゃうと、マジで保守大変よ。
10. AAA(Arrange、Act、Assert)を意識したテストコードを書く
Arrange(準備)、Act(実行)、Assert(検証)
これもそうねonigiri.w2.icon
めっちゃ大切やと思う。この形式で全てのコードが書かれることで、テストコードに一貫性ができて読みやすくなる。
テストを自動化したからといって、手動テストが全く不要になるわけではない。
以下のようなケースではローカルマシン、またはステージング環境で手動テストを実施すること。
画面上の見た目、外部リソースとの連携、重要度の高いユースケース部分、自動テストを諦めたロジック、など
なるほど、自動テストで無理やり全て解決しなくてもいいのねonigiri.w2.icon
あまりここら辺は実感がわかんな。自動テストすらちゃんとできてないし。
まあ、自分は線引きよくわからんくて、全部自動テストしちゃってる節ある。
上位のテストでエラーになったパターンを下位のテストケースに追加するということは重要です。
そうだな、上位テスト(結合テストなど)で見つかったバグは、2度と起こらないように、バグの原因となった下位テストでテストコードを書き、自動テストをしやすくしておくのが大事だろうonigiri.w2.icon
開発と動作確認の素早いサイクルを構築することで、開発効率、開発体験の向上
これも単体テストを書くときの1つ目の目的だな。
意外と手動でデバッグするのって面倒だし、時間かかる、その上で「なんかちゃんと動くんかな、このコード」的な不安を払拭できない。
ちゃんとテストコード書いてると安心して次に進める。その上、行ったり来たりしなくていいから開発スピードも普通に上がる。
コードを修正した場合のリグレッション(後退)の確認としても使える
これもそうね、変更にはいつだってバグが隠れてると思うといい。
というか変更があるからバグが入るんだよな。
今まで動いてたシステムが変更後もちゃんと動くことを確認するためには、自動テストの仕組みを作っておくことが大事。
特に単体テスト部分は、自動テストしておくのがいいだろう。言語化できんけどonigiri.w2.icon
結合テストを作成する際に、単体テスト(テストコード)の内容を把握しないといけない、といったことは起きません。単体テストと結合テストではそもそもターゲットとしているスコープが異なります。
うん、単体テストと結合テストでは、目的が異なってくるよなonigiri.w2.icon
単体テストは部品が責務通りに動くことを確認する箇所
結合テストなどは、部品よりも大きなシステムが部品通しの組み合わせでちゃんと動くかを確認する箇所
実際、単体テストが全て通ってるからと言って、システムが正常に動くとは限らないんよ。
外部リソースとの連携とか、入出力の違いとか、そういうのでシステム全体としてはバグがあったりするってこともある。
あと、単体テストのテストケースに漏れがあったりすることもある。
そういうのが無いよう、システム作成の最後でしっかりシステム全体の仕様がうまく動くかをテストしたりするんよな。
良いテストコードというのは、プログラムがどんな仕様でどんな動きをしているのかが読み取りやすいコードです。
そう思うonigiri.w2.icon
テストコードにバグがあるかどうかを正確に判断できないと、テストがOKだとしても意味ない。普通に本番コードにテストが含まれてる可能性ある。
だから、テストコードを読むことで、本番コードの仕様が理解でき、そのチェック項目を正確にチェックできるテストコードになってることを簡単に確認できないといけない。
レビュー時に、テストコードの内容を全て理解せずに承認するのは狂気の沙汰で、本番コードにバグが含まれてる可能性があるのを許してることになる。
ちゃんと正しくバグが入ってないことを確認できるよう、わかりやすいテストコードにしようって話だ。
DRYを目指せば目指すほど、テストコードのわかりやすさは失われていく傾向にあります。
テストコードを理解するのに、あっちこっち行ったり来たりする恐れあるし、なんかよくわからん事前処理が走ってたりすると厄介。マジクソ。
読みやすいテストコードの3条件
1. ドキュメントのように上から下に読み下せる
2. 変数を使わずに文字列や数値をベタ書きする
3. 凝ったテクニックを濫用しない
これはあれだな、本番コードの仕様を簡単に把握できるようにし、足りないテストケースに漏れがないかを簡単に見つけれるようにし、その上で、テストコードがそのチェック項目を正しくチェックできるかを確認する必要があるんだよonigiri.w2.icon
そのために、こういった「わかりやすく3条件」を守れて話なんだな多分。
本番コードが正しく動いてるかってうのは以下のような感じだな。
1. 想定してる仕様が正しいか
2. その仕様を満たすようなコードになってるか
ここをレビュー時にチェックする。
その際、テストコードを見ることで「1」を確認できるようにするのかも、また、「1」に対して十分なテストケースが存在するかも確認できる。
あと本番コードがちゃんと動くことを確認するためのテストコードにもバグがないことを保証する必要あり。
そのためにはテストコードをちゃんと読む必要がある。
そのテストコードを読む際に、隠れた前提条件とかあるとたまったもんじゃない。
わかりやすくかけと。理解しやすくな。
脳内メモリを消費するテストコードを読みやすくする方法
パッと見て何に対してどんなテストをしてるのかわからんなら、メモリを消費してるということ。
変数とかあったら、その変数に入ってる値を探したりすることになる。しんどい。
システムテスト:本番に近いテストができる(ユーザーが実際に動かした際の動作確認的なイメージ)
ユニットテスト:部品が責務通りに動くことをテストする
統合テスト:ユニットテストでモック化してた外部リソースとかをちゃんとしたやつ使ってテストするイメージ。部品だけではテストできないポイントを一緒にテストするような。
なんとなくイメージできたわonigiri.w2.icon
良いユニットテストを書くために
考え方:
・意図を伝えるテスト
・テストを独立させる
・重複を最小限に
・テスト容易な設計
意図がちゃんと伝わるテストって感じかな。大事。
結局、本番コードに対して何をテストしたいのかが明確じゃないとテストを書いて何を保証してるのかわからん。
テスト独立も大事で、テストコードにバグが入らんようにな。
重複を最小限にはあまり賛同できない。
重複を最小限にしようとすると、テストが読みにくくなると思う。
テスト容易な設計は賛成
テストがしんどいのは、設計がうまくいってない可能性ある
意図を伝えるテスト
つまり、テスト対象の本番コードがどういう仕様を持ってるのかを、テストコードだけで把握できるようにしろってこと。
そもそも、テストは本番コードが仕様通りに動いてることを確認するためのもの。
なので、テストコードを読むことで、対象の本番コードの仕様がわかるのは自然。
テストコードが仕様を確認するものになってるかをいちいちドキュメントから確認するのは二度手間なので、テストコード自体から分かるようにしようと。そういうこと。
テストケース同士が依存関係にあったり、テストケースの順序がテスト結果に関わってたりする状況はだめ
めちゃくちゃ脆弱、不安定な状況なので注意しよう。
例えば、あるテストケースが必要無くなったから、丸々削除した時に、そのケースに依存してる他ケースがあると、そいつが落ちる。
他のケースの状況に依存させるんじゃねぇ。
外部システムとの関係性は常に疎結合であるように努力しろ
単体テストだからな、外部システムに影響しちゃったら、テストが不安定になっちまう。
そういうのは統合テストでやろう。
前提条件などをテストケース間で共通化(DRY)するな。テストケース間の独立性がなくなる。しんどい。
例えば、他のテストケースの都合で、前提条件の内容を変えた際、別のテストケースに影響が出る可能性あり。
まあ、全部が全部共通化するなというわけではない、本当に共通化した方がいいものだけ共通化しろ。
むやみに全部共通化するな、保守できなくなるぞ。
私の経験では、ユニットテストはアルゴリズムロジックに対して行う時に最も有益です。結合度の高いコードについてはその性質から特に有益ではありません。結合度が高いコードはユニットテストのために多くのモックオブジェクトを必要としますが、テストそのものがそれほど関心があるものではありません。この種のコードはユニットテストからは多くのメリットを得られませんが、それに代わって統合テストにおいてよりよいテストができます。
ほおおおおおおお、なるほどonigiri.w2.icon
「結合度高い部品に関しては、結合テストをした方がいい」と、なるほど。確かに。
マジでモック作るのしんどいからな。結合度高いと。
いや、この考え方取り入れたいな。
確か「モック使ったテストは意味ない」的な話もあったよな、そこら辺も調べてみないと。
十分テストされた部品。 アプリケーション全体をテストする場合に、十分テストされた部品を使うと好都合です。それは簡単な部品から機能を構成していく標準的なボトムアップ手法です。前述した例では、プールの機能のユニットテストが行われていれば、システム全体をテストする時に、残りのシステムに集中して動作確認をすることができます。もしユニットテストが行われていなければ、プールの動作に問題が発見されるかもしれませんが、コードの中で問題がどこにあるのか見つけるためには多くの労力が必要になるでしょう。どこかに問題が潜んでいる可能性はあるのですから。
これは本当にそうだと思う。
統合テストでバグが見つかった時、ユニットテストのあるなしで大変さが変わる。
どの部品にバグがあるのか?から探すのだるい。
各部品の動作が保証されてるなら、その部品をバグの要因から外せる。
まあ、既に上記に書かれてるようなことが記載されてた。
高橋さんによると、彼らはE2Eのテストは殆どしないらしく、聞くと「意味ないでしょ」という事らしいです。
統合テストはするよな?onigiri.w2.icon
外部システムとのつながりの動作テストはやるはずや、知らんけど。
システムテストはやらんのか、へぇ。
単体テスト、統合テストができてるなら動くっていう話なんかな。
まあ、システムテストって時間かかりそうやんな。そんでもって仕様変更の影響受けやすいから保守もだるそう。
システムテストするくらいなら、すぐリリースしてバグ見つけた方が早そう。
期待する操作で期待する結果になることを厳密に検証する
別操作で期待される結果が得られてかもしれない。そういう気持ちを持ってテストコード書く。
そういう余地が入り込まないよう、厳密にテストコードを...。
テストタイトルには期待するふるまいを書く
テストタイトルには、厳密な振る舞い内容を書くこと。
それが仕様になるんだよ。
「正しく動いてる」てのは仕様じゃねえ。
私の経験では、コードが一見しただけでは明らかでない場合 (その正確な動作を理解するには時間と慎重な検討が必要です)、追加の設計と検証の支援 (たとえば、単体テストによる) が不可欠です。
そうやなonigiri.w2.icon
逆に、コードが基本的に明白であり、一目でその機能が正確にわかる場合、追加の設計と検証 (たとえば、単体テストによる) は、たとえあったとしてもごくわずかな利益しかもたらしません。
そうやなonigiri.w2.icon
まあ、ここの見極めが経験不足だと難しくもあったりして「やっぱテストしておいた方が安心できる」とはなりそう。
依存関係がほとんどない複雑なコードを持つ部品は単体テストしろ
なるほど、これはモックとか作る必要ないし、簡単に単体テストできそう。
それでいて、複雑なコードなので動作をちゃんとチェックしておきたいよなうん
依存関係が多く、複雑なコードを持つ部品は本番コードを分解しろ。
これは本番コード分解しない場合は、結合テストするんかな?
依存度多いと、モック大量に作ることになってマジでだるいからな....
依存関係がなく、コードも複雑じゃない動作が自明な部品
これはもう単体テスト書くな。いらん。時間の無駄。ってことらしい。
まあ分かる。
依存関係が多く、簡単なコードを持つ部品
これは単体テスト書かなくていいらしい。
結合テストわんちゃんくらい?
一つ疑問なんだが、結合テストってどう表現するんだ???
pytest的なフレームワークがあるのか、pytestを使っていい感じにやるのか
まあ、ここはpytestを使って、単体テスト、結合テストをいい感じ明示してやるんだろうな。